home *** CD-ROM | disk | FTP | other *** search
/ JCSM Shareware Collection 1993 November / JCSM Shareware Collection - 1993-11.iso / cl720 / qbnws31j.lzh / XMS.ASM < prev    next >
Assembly Source File  |  1992-02-01  |  22KB  |  523 lines

  1. ;****************************************************************************
  2. ; XMS.ASM - Extended memory interface for QuickBASIC programs.
  3. ;
  4. ; (C) Copyright 1992 by Sequential Software. All rights reserved.
  5. ; Author: Robin Duffy.
  6. ;
  7. ; See the headers for each public routine on calling syntax and operating
  8. ; notes. Use of extended memory requires HIMEM.SYS to be installed via
  9. ; CONFIG.SYS and a 80286 or later processor. Each procedure may be
  10. ; called at any time, even if no XMS is installed on the host machine.
  11. ;
  12. ; Assembled with Turbo Assembler 2.5
  13. ;****************************************************************************
  14. .Model Medium, Basic
  15.  
  16. .Data
  17.  
  18. XError    db   80h                      ;Storage for errors, assumes no XMS
  19. XMSThere  dw   0                        ;XMS available flag, assumes no XMS
  20. XMove     dw   8 Dup(?)                 ;Buffer for array move routines
  21.  
  22. .Code
  23.  
  24. XMSDriver dw ?,?                        ;Local storage for HIMEM entry point
  25.  
  26.                     Public    InitXMS
  27. ;****************************************************************************
  28. ; Procedure to check for HIMEM.SYS and initialize a few things. This routine
  29. ; must be called prior to calling any of the other procedures.
  30. ;
  31. ; Syntax: CALL InitXMS(There%, MemSize%)
  32. ; Returns:     There% =  0 No XMS available
  33. ;                     = -1 XMS available
  34. ;
  35. ;            MemSize% = Size of available XMS in K bytes.
  36. ;                       Valid only if There% is not zero.
  37. ;****************************************************************************
  38. Proc InitXMS   Uses ES, There:Ptr Word, MemSize:Ptr Word
  39.  
  40.     Mov   AX,4300h                      ;Prepare to do installation check
  41.     Int   2fh                           ;Use the multiplex interrupt
  42.     Cmp   AL,80h                        ;Is HIMEM.SYS installed?
  43.     Jnz   InitExit                      ;Nope, get on out
  44.  
  45.     Mov   AX,4310h                      ;Get the driver entry point
  46.     Int   2fh
  47.  
  48.     Mov   CS:XMSDriver,BX               ;Store the offset of entry point
  49.     Mov   BX,ES
  50.     Mov   CS:XMSDriver[2],BX            ;And the segment of entry point
  51.  
  52.     Sub   BL,BL                         ;HIMEM does not clear this
  53.     Mov   AX,0800h
  54.     Call  DWord Ptr CS:XMSDriver        ;Find available extended memory size
  55.     Or    BL,BL                         ;Did an error occur?
  56.     Jnz   InitExit                      ;Yes, so get out now
  57.  
  58.     Cmp   AX,0                          ;Is there any left for us?
  59.     Jz    InitExit                      ;No, exit now
  60.  
  61.     Mov   BX,MemSize
  62.     Mov   [BX],AX                       ;Report the available size
  63.     Dec   XMSThere                      ;Mark our flag to -1 (XMS is good)
  64.     Mov   XError,0                      ;Clear the error variable
  65.  
  66. InitExit:
  67.     Mov   AX,XMSThere
  68.     Mov   BX,There
  69.     Mov   [BX],AX                       ;Report results to BASIC
  70.     Ret                                 ;And return
  71.  
  72. InitXMS   EndP
  73.  
  74.  
  75.                     Public    GetXMS
  76. ;***************************************************************************
  77. ; Procedure to allocate extended memory for the program. Because this is a
  78. ; function, it must be declared before it may be used.
  79. ; Syntax: Handle% = GetXMS(Size%)
  80. ;         where Handle% receives the XMS handle. All further references to
  81. ;         this block require this handle (much like DOS file handles). A
  82. ;         handle of 0 means an error allocating the memory.  This system
  83. ;         allows multiple blocks to be managed by the parent program.
  84. ;
  85. ;         Size% is the requested memory size in K bytes.
  86. ;***************************************************************************
  87. GetXMS    Proc Amount:Ptr
  88.  
  89.      Cmp  XMSThere,-1                   ;Any point in continuing?
  90.      Jnz  GetExit                       ;Nope.
  91.  
  92.      Mov BX,Amount
  93.      Mov  DX,[BX]                       ;Get the K requested by user
  94.  
  95.      Sub  BL,BL
  96.      Mov  AX,0900h
  97.      Call DWord Ptr CS:XMSDriver        ;Ask HIMEM for it
  98.      Mov  XError,BL                     ;Save error code
  99.  
  100.      Cmp  AL,1                          ;Was it allocated?
  101.      Jz   AllOK                         ;Yes, go return handle
  102.      Sub  DX,DX                         ;Otherwise return handle of zero
  103.  
  104. AllOK:
  105.      Mov  AX,DX                         ;Return handle as function output
  106.  
  107. GetExit:
  108.      Ret                                ;Return to BASIC
  109.  
  110. GetXMS    EndP
  111.  
  112.                     Public    FreeXMS
  113. ;***************************************************************************
  114. ; Procedure to release extended memory blocks.
  115. ;
  116. ; Syntax: CALL FreeXMS(Handle%)
  117. ;         where Handle% is the block handle assigned by GetXMS.  This should
  118. ;         be called prior to exiting your program. Unlike conventional
  119. ;         memory, extended memory is not automatically released by DOS
  120. ;         when the program ends. The memory remains allocated.
  121. ;***************************************************************************
  122. FreeXMS   Proc Uses SI, Handle:Ptr Word
  123.  
  124.      Cmp  XMSThere,-1                   ;Any point in continuing?
  125.      Jnz  FreeExit                      ;Nope.
  126.  
  127.      Mov  SI,Handle
  128.      Call CheckHandle                   ;Make sure it is a valid handle
  129.      Cmp  XError,0                      ;Error occur?
  130.      Jnz  FreeExit                      ;Yes, get out now!
  131.      
  132.      Mov  DX,[SI]                       ;Place user handle in DX
  133.      Sub  BL,BL
  134.      Mov  AX,0a00h
  135.      Call DWord Ptr CS:XMSDriver        ;Tell HIMEM to release the block
  136.      Mov  XError,BL                     ;Save error code
  137.      
  138. FreeExit:
  139.      Ret                                ;And return to BASIC
  140.  
  141. FreeXMS   EndP
  142.  
  143.  
  144.                     Public    Array2XMS
  145. ;****************************************************************************
  146. ; Procedure to move a block of memory from conventional to XMS memory.
  147. ;
  148. ;Syntax: CALL Array2XMS(BYVAL FromSeg%, BYVAL FromOffset%, Handle%, NumBytes&)
  149. ;                             or
  150. ;         CALL Array2XMS(SEG Array(1), Handle%, Numbytes&)
  151. ;
  152. ;         FromSeg% = Segment of source block
  153. ;         FromOffset% = Offset of source block
  154. ;         Handle% = XMS handle assigned by GetXMS
  155. ;         NumBytes& = number of bytes to move (must be even)
  156. ;                     if a constant is used, it must be declared long
  157. ;
  158. ;****************************************************************************
  159. Array2XMS Proc Uses SI, SSeg:Ptr Word, SOff:Ptr Word, Handle:Ptr Word,\
  160.                         Bytes:Ptr Word
  161.                                 
  162.      Cmp  XMSThere,-1                   ;Any point in continuing?
  163.      Jnz  Mov1Exit                      ;Nope.
  164.  
  165.      Mov  SI, Handle                    ;Pass handle address to CheckHandle
  166.      Call CheckHandle                   ;See if the handle is defined
  167.      Cmp  XError,0                      ;If error then exit
  168.      Jnz  Mov1Exit                      ;Exit with error already set
  169.  
  170.      Mov  SI,Offset XMove               ;Get location of our XMS structure
  171.  
  172.      Mov  BX,Bytes                      ;Starts with number of bytes to move
  173.      Mov  AX,[BX]                       ;Read low word
  174.      Mov  DX,[BX+2]                     ;Read high word (long integer)
  175.  
  176.      Test AX,1                          ;Is it odd?
  177.      Jz   IsEven                        ;No, it's OK
  178.      Dec  AX                            ;Force it even
  179.      
  180. IsEven:
  181.      Mov  [SI],AX                       ;Load low word of number of bytes
  182.      Mov  [SI+2],DX                     ;Load the high word
  183.  
  184.      Mov  Word Ptr [SI+4],0             ;Source handle is conventional memory
  185.      Mov  BX,SOff                       ;Load source offset
  186.      Mov  [SI+6],BX
  187.      Mov  BX,SSeg                       ;Load source segment
  188.      Mov  [SI+8],BX
  189.  
  190.      Mov  BX,Handle                     ;Load destination XMS handle
  191.      Mov  AX,[BX]
  192.      Mov  [SI+10],AX
  193.      
  194.      Mov  Word Ptr [SI+12],0           ;Offset 0 into XMS block
  195.      Mov  Word Ptr [SI+14],0
  196.  
  197.      Sub  BL,BL
  198.      Mov  AX,0b00h                      ;Ask HIMEM to do it for us
  199.      Call DWord Ptr CS:XMSDriver        
  200.      Mov  XError,BL                     ;Save the error code
  201.  
  202. Mov1Exit:
  203.      Ret                                ;Back to the BASIC's....
  204.  
  205. Array2XMS EndP
  206.  
  207.                     Public    XMS2Array
  208. ;***************************************************************************
  209. ; Procedure to move a block from XMS to conventional memory.
  210. ;
  211. ; Syntax: CALL XMS2Array(Handle%, BYVAL ToSeg%, BYVAL ToOffset%, NumBytes&)
  212. ;                             or
  213. ;         CALL Array2XMS(Handle%, SEG Array(1), Numbytes&)
  214. ;
  215. ;         Handle% = XMS handle assigned by GetXMS
  216. ;         ToSeg% = Segment of destination block
  217. ;         ToOff% = Offset of destination block
  218. ;         NumBytes& = number of bytes to move (must be even)
  219. ;****************************************************************************
  220. XMS2Array Proc Uses SI, Handle:Ptr Word, ToSeg:Ptr Word, ToOff:Ptr Word,\
  221.                         Bytes:Ptr Word
  222.  
  223.      Cmp  XMSThere,-1                   ;Any point in continuing?
  224.      Jnz  Mov2Exit                      ;Nope.
  225.  
  226.      Mov  SI, Handle                    ;Pass handle address to CheckHandle
  227.      Call CheckHandle                   ;See if the handle is defined
  228.      Cmp  XError,0                      ;If error then exit
  229.      Jnz  Mov2Exit                      ;Exit with error already set
  230.  
  231.      Mov  SI,Offset XMove               ;Get location of our XMS structure
  232.      
  233.      Mov  BX,Bytes                      ;Starts with number of bytes to move
  234.      Mov  AX,[BX]                       ;Read the low word
  235.      Mov  DX,[BX+2]                     ;Read the high word (long integer)
  236.      
  237.      Test AX,1                          ;Is it odd?
  238.      Jz   Is2Even                       ;They read the manual again!
  239.      Dec  AX                            ;Force it even
  240.  
  241. Is2Even:
  242.      Mov  [SI],AX                       ;Load low word
  243.      Mov  [SI+2],DX                     ;Now the high one
  244.  
  245.      Mov  BX,Handle                     ;Load the XMS source block handle
  246.      Mov  AX,[BX]
  247.      Mov  [SI+4],AX
  248.  
  249.      Mov  Word Ptr [SI+6],0            ;Offset 0 into XMS block
  250.      Mov  Word Ptr [SI+8],0
  251.  
  252.      Mov  Word Ptr [SI+10],0            ;Destination is conventional memory
  253.      Mov  BX,ToOff                      ;Load destination offset
  254.      Mov  [SI+12],BX
  255.      Mov  BX,ToSeg                      ;Load destination segment
  256.      Mov  [SI+14],BX
  257.  
  258.      Sub BL,BL
  259.      Mov  AX,0b00h                      ;Ask HIMEM to do it for us
  260.      Call DWord Ptr CS:XMSDriver        
  261.      Mov  XError,BL                     ;Save the error code
  262.  
  263. Mov2Exit:
  264.      Ret                                ;Back to the BASIC's....
  265.  
  266. XMS2Array EndP
  267.  
  268.                     Public XGetElement
  269. ;***************************************************************************
  270. ; Procedure to return any continuous portion of an array stored in XMS.
  271. ;
  272. ; Syntax: CALL GetElement(Handle%, Variable, EleLen%, EleNum%)
  273. ;    where Handle% - handle assigned by GetXMS
  274. ;          Variable - variable (TYPE, fixed string, or integer) to set
  275. ;          EleLen% - length of the variable in bytes
  276. ;          EleNum% - element number to retrieve
  277. ;
  278. ; Variable can be any variable type except a conventional string. It
  279. ; should be noted that EleLen% should be even. Also, this procedure
  280. ; assumes the first element of the array is element number one. That is,
  281. ; assume all arrays are one-based.
  282. ;***************************************************************************
  283. XGetElement     Proc Uses SI, Handle:Ptr Word, Vari:Ptr Word, EleLen:Ptr Word,\
  284.                              EleNum:Ptr Word
  285.  
  286.      Cmp  XMSThere,-1                   ;Any point in continuing?
  287.      Jnz  GEExit                        ;Nope.
  288.  
  289.      Mov  SI, Handle                    ;Pass handle address to CheckHandle
  290.      Call CheckHandle                   ;See if the handle is defined
  291.      Cmp  XError,0                      ;If error then exit
  292.      Jnz  GEExit                        ;Exit with error already set
  293.  
  294.      Mov  XError,0a7h                   ;Assume a syntax error
  295.      Mov  SI,Offset XMove               ;Location of our move buffer
  296.      Sub  DX,DX                         ;Make sure DX is zero (oops!)
  297.  
  298.      Mov  BX,EleLen                     ;Get the length of the variable
  299.      Mov  AX,[BX]                       ;Load into AX
  300.      Test AX,1                          ;Is it odd?
  301.      Jz   Is3Even                       ;No, it's OK.
  302.  
  303.      Dec  AX                            ;Make it even
  304.      Or   AX,AX                         ;It's not zero, is it?
  305.      Jnz  Is3Even                       ;No, it's OK.
  306.      Jmp  Short GEExit                  ;It is zero, leave now
  307.  
  308. Is3Even:
  309.      Mov  BX,EleNum                     ;Get the element to get
  310.      Mov  CX,[BX]                       ;into CX
  311.      Jcxz GEExit                        ;If element is 0, forget it
  312.  
  313.      Mov  XError,0                      ;We are OK here, clear error status
  314.      Mov  [SI],AX                       ;EleLen is number of bytes to move
  315.      Mov  [SI+2],DX                     ;High word should be zero.....
  316.  
  317.      Dec  CX                            ;Adjust CX to zero base
  318.      Mul  CX                            ;Find offset into block
  319.                                         ;DX:AX holds 32 bit offset into block
  320.      Mov  BX,Handle                     ;Find our source handle
  321.      Mov  CX,[BX]
  322.      Mov  [SI+4],CX                     ;Move handle into buffer
  323.      Mov  [SI+6],AX                     ;Low word of 32 bit offset
  324.      Mov  [SI+8],DX                     ;High word of offset
  325.  
  326.      Mov  Word Ptr [SI+10],0            ;Destination handle is convential mem
  327.      Mov  BX,Vari                       ;Get offset of variable from BASIC
  328.      Mov  [SI+12],BX                    ;Load offset into structure
  329.      Mov  [SI+14],DS                    ;Set segment to DS
  330.  
  331.      Sub BL,BL
  332.      Mov  AX,0b00h                      ;Ask HIMEM to do it for us
  333.      Call DWord Ptr CS:XMSDriver
  334.      Mov  XError,BL                     ;Save the error code
  335.  
  336. GEExit:
  337.      Ret                                ;Back to BASIC
  338.  
  339. XGetElement     EndP
  340.  
  341.  
  342.                     Public XSetElement
  343. ;***************************************************************************
  344. ; Procedure to set any continuous portion of an array stored in XMS.
  345. ;
  346. ; Syntax: CALL SetElement(Handle%, Variable, EleLen%, EleNum%)
  347. ;    where Handle% - handle assigned by GetXMS
  348. ;          Variable - variable (TYPE, fixed string, etc) to place in XMS
  349. ;          EleLen% - length of the variable in bytes
  350. ;          EleNum% - element number to write to
  351. ;
  352. ; Variable can be any variable type except a conventional string. It
  353. ; should be noted that EleLen% should be even. Also, this procedure
  354. ; assumes the first element of the array is element number one. That is,
  355. ; assume all arrays are one-based.
  356. ;***************************************************************************
  357. XSetElement    Proc Uses SI, Handle:Ptr Word, Vari:Ptr Word, EleLen:Ptr Word,\
  358.                              EleNum:Ptr Word
  359.  
  360.      Cmp  XMSThere,-1                   ;Any point in continuing?
  361.      Jnz  SEExit                        ;Nope.
  362.  
  363.      Mov  SI, Handle                    ;Pass handle address to CheckHandle
  364.      Call CheckHandle                   ;See if the handle is defined
  365.      Cmp  XError,0                      ;If error then exit
  366.      Jnz  SEExit                        ;Exit with error already set
  367.  
  368.      Mov  XError,0a7h                   ;Assume a syntax error
  369.      Mov  SI,Offset XMove               ;Location of our move buffer
  370.      Sub  DX,DX                         ;Make sure DX is zero (oops again!)
  371.  
  372.      Mov  BX,EleLen                     ;Get the length of the variable
  373.      Mov  AX,[BX]                       ;Load into AX
  374.      Test AX,1                          ;Is it odd?
  375.      Jz   Is4Even                       ;No, it's OK.
  376.  
  377.      Dec  AX                            ;Make it even
  378.      Or   AX,AX                         ;It's not zero, is it?
  379.      Jnz  Is4Even                       ;No, it's OK.
  380.      Jmp  Short SEExit                  ;It is zero, leave now
  381.  
  382. Is4Even:
  383.      Mov  BX,EleNum                     ;Get the element to write to
  384.      Mov  CX,[BX]                       ;into CX
  385.      Jcxz SEExit                        ;If element is 0, forget it
  386.  
  387.      Mov  XError,0                      ;We are OK here, clear error status
  388.      Mov  [SI],AX                       ;EleLen is number of bytes to move
  389.      Mov  [SI+2],DX                     ;High word should be zero
  390.  
  391.      Dec  CX                            ;Adjust CX to zero base
  392.      Mul  CX                            ;Find offset into block
  393.                                         ;DX:AX holds 32 bit offset into block
  394.      Mov  Word Ptr [SI+4],0             ;Source handle is convential mem
  395.      Mov  BX,Vari                       ;Get offset of variable from BASIC
  396.      Mov  [SI+6],BX                     ;Load offset into structure
  397.      Mov  [SI+8],DS                     ;Set segment to DS in structure
  398.  
  399.      Mov  BX,Handle                     ;Find our source handle
  400.      Mov  CX,[BX]
  401.      Mov  [SI+10],CX                    ;Move handle into buffer
  402.      Mov  [SI+12],AX                    ;Low word of 32 bit offset in buffer
  403.      Mov  [SI+14],DX                    ;High word of offset in buffer
  404.  
  405.      Sub BL,BL
  406.      Mov  AX,0b00h                      ;Ask HIMEM to do it for us
  407.      Call DWord Ptr CS:XMSDriver
  408.      Mov  XError,BL                     ;Save the error code
  409.  
  410. SEExit:
  411.      Ret                                ;Back to BASIC
  412.  
  413. XSetElement     EndP
  414.  
  415.                     Public    XMSError
  416. ;****************************************************************************
  417. ; Procedure to report success of last XMS operation. Because this is a
  418. ; function, It must be declared before it may be used.
  419. ;
  420. ; Syntax: C% = XMSError%
  421. ;
  422. ;    returns C% = 0  Last operation successful
  423. ;            C% = -1 Last operation resulted in error
  424. ;
  425. ;    This function will always show an error if XMS is not available.
  426. ;****************************************************************************
  427. XMSError  Proc
  428.  
  429.      Mov  AX,-1                    ;Assume an error
  430.      Cmp  XMSThere,0               ;Is XMS available?
  431.      Jz   ExitErr                  ;No, exit now with error
  432.  
  433.      Mov  BL,XError                ;Load error byte in
  434.      Or   BL,BL                    ;Anything there?
  435.      Jnz  ExitErr                  ;Yes, report an error
  436.      Inc  AX                       ;Make it a 0 to show no error
  437.  
  438. ExitErr:
  439.      Ret                           ;Back to BASIC with output in AX
  440.  
  441. XMSError  EndP
  442.  
  443.                     Public    WhichXError
  444. ;***************************************************************************
  445. ; Procedure that returns the current value of XError. Because this is a
  446. ; function, it must be declared before it may be used. It should be noted
  447. ; that any sucessful call to any procedure in this file will clear XError.
  448. ;
  449. ; Syntax:  Code% = WhichXError%
  450. ;    where Code% receives the value of XError.
  451. ;***************************************************************************
  452. WhichXError    Proc
  453.  
  454.      Mov  AL,XError                     ;Load AL with the error
  455.      Xor  AH,AH                         ;Clear AH
  456.      Ret                                ;Return to BASIC
  457.  
  458. WhichXError    EndP
  459.  
  460.                     Public    SetXError
  461. ;****************************************************************************
  462. ; This procedure allows direct setting of the XError variable to force
  463. ; error codes. Useful for communications between modules.
  464. ;
  465. ; Syntax: CALL SetXError(ErrCode%)
  466. ;    where ErrCode% is a value between 0 - 255 inclusive.
  467. ;
  468. ; Note: If XMS is not installed, this function will not have any effect.
  469. ;****************************************************************************
  470. SetXError Proc ErrCode:Ptr Word
  471.  
  472.      Cmp  XMSThere,-1                   ;Can we set error codes?
  473.      Jnz  SetExit                       ;No, skip this
  474.      
  475.      Mov  BX,ErrCode                    ;Get the user's error code
  476.      Mov  AX,[BX]                       ;into AX
  477.      Mov  XError,AL                     ;Load it
  478.  
  479. SetExit:
  480.      Ret                                ;Back to BASIC
  481.  
  482. SetXError EndP
  483.  
  484. ;****************************************************************************
  485. ; CheckHandle - Procedure to test the validity of a user passed handle. For
  486. ;               some reason HIMEM.SYS does not seem to check the validity of
  487. ;               the handle on any function call but this one!  If not tested
  488. ;               an invalid handle will lock the machine.
  489. ;
  490. ; On Entry: SI - pointer to address of user passed handle
  491. ;
  492. ; On Exit: DX - block size associated with handle
  493. ;          XError - set to invalid handle if invalid, otherwise clear
  494. ;****************************************************************************
  495.  
  496. CheckHandle    Proc Near
  497.      Mov  DX,[SI]                       ;Put the handle in DX
  498.      Or   DX,DX                         ;Handle of zero?
  499.                                         ;Note: I test for a zero handle
  500.                                         ;becuase 0 is a valid handle for
  501.                                         ;HIMEM (conventional memory) but is
  502.                                         ;NOT valid for any user calls.
  503.      Jnz  DXOK                          ;It's not, go on
  504.      Mov  XError,0a2h                   ;Set "Invalid Handle" error
  505.      Jmp Short CHExit                   ;And exit
  506.  
  507. DXOK:
  508.      Sub  BL,BL                         ;Clear BL for HIMEM
  509.      Mov  XError,BL                     ;and the error code
  510.  
  511.      Mov  AX,0e00h
  512.      Call DWord Ptr CS:XMSDriver        ;Ask HIMEM about this handle
  513.  
  514.      Cmp  AX,1                          ;Was it successful?
  515.      Je   CHExit                        ;Yes, exit now
  516.      Mov  XError,BL                     ;Save the error code
  517.  
  518. CHExit:
  519.      Ret
  520. CheckHandle    EndP
  521.  
  522. End 
  523.